home *** CD-ROM | disk | FTP | other *** search
- Path: news.compuserve.com!newsmaster
- From: Philippe Verdy <100105.3120@compuserve.com>
- Newsgroups: comp.lang.c++
- Subject: Re: What's mean about '...'
- Date: 24 Mar 1996 00:27:40 GMT
- Organization: CompuServe Incorporated
- Message-ID: <4j24ts$shm@arl-news-svc-3.compuserve.com>
- NNTP-Posting-Host: ad53-232.compuserve.com
-
- cywong@asiaonline.net (Wong Chi Yat) s'Θcrit :
- > Could you tell me what's mean about "..." which is defined in C language
- > procedure, e.g. void test(char *t, ...)
- >
- > I wish you could tell me how to implement?
- >
- > Thank you very much?
- >
- > e-mail: cywong@asiaonline.net
- > A
- >
- "..." is a placeholder for unknown parameters, so it is not
- conforming to the C++ strict-typing philosophy. As far as I
- know, the only places where it appears in the C library is for
- XXXprintf() and XXXscanf() functions. These functions are
- dangerous in C and also in C++, because there is no type-checking
- and all is done by interpreting their first (char*format)
- argument. If the string is invalid, segment violation will
- occur. Also, there is no way to limit very safely the limit
- of data written or read from those functions. That's why
- C++ streams have been created, and no C++ RTL/STL functions
- use them.
-
- However they are still permitted. Use them like this:
-
- #include <stdarg.h> // ANSI-C/C++ support for varying arguments
- // ...
- int logprintf(char *format, ...)
- {
- char buffer[1024];
- va_list args;
-
- va_start(args, format);
- vsprintf(buffer, format, args);
- va_end(args);
- clog << buffer;
- }
-
- va_start initialise an argument pointer pointing to the unknown
- arguments of the function. This pointer is useable as is for
- calling vXXXprintf() or vXXXscanf() functions (which have
- fixed arguments, and are type-safe on these arguments only).
-
- va_end is required once we have ended using the varying
- arguments list. On most platforms it does not make anything
- but it is not always true (va_start may on some platforms
- build-up a stack segment to access those parameters which
- otherwise would only be accessible thru processor registers,
- forgetting to use va_end could produce memory leaks or could
- crash the function when it exits !)
-
- You can parse each varying argument, provided you have a
- model of how they are disposed. On XXXprintf and XXXscanf
- functions, the model is the format string which is scanned
- in order to find out what kind or arguments are expected.
- Parsing these arguments will always be done from left to
- right, taking one parameter at a time. To rescan the parameters
- you must first use va_end(args), then recall va_start(args).
- The arguments pointer (args) is always of type (va_list)
-
- To get the next varying argument of type T, use:
- va_list args;
- T vararg1; // variables to store values of
- char * vararg2; // varying arguments
-
- va_start(args, lastfixed); // init
- ...
- vararg1 = va_arg(args, T); // use it repeatedly
- vararg2 = va_arg(args, char *); // use it repeatedly
- ...
- va_end(args); // end
- this will get the value of that argument, and advance the args
- pointer to next argument. Varying arguments can have any type
- valid in C.
-
- Do not compute the new value of args yourself: the size of T
- is not always the size by which the argument pointer is moved
- forward, and sometimes this pointer is incremented or
- decremented (depending on the platform stack implementation).
-
- So not assume also that args is directly pointing to the argu
- ment itself: it could point on another place, depending on the
- type of the argument, or it could be an internal argument
- index, used in functions called by the va_arg() macro !
-
- Do not use va_arg() to get other arguments than those which
- are specified as unknown : depending on the architecture, the
- compiler could generate different memory models for fixed and
- varying arguments ! The argument name you give to va_start
- is the last fixed argument before the "..." specifier.
-
- You need at least one fixed argument before the varying ones.
- This is a major difference with the old K&R-style <varargs.h>
- macros for accessing varying arguments.
-
- As for all macros which have side effects on some variables,
- do not use them several times within an expression, because
- these macros are often complex and the order of evaluation
- is important and could give unexpected results. For example,
- do not use the following:
- ...
- my_func(va_arg(args, int), va_arg(args, int));
- ...
- which is very implementation dependant, but use:
- int a, b;
- ...
- a = va_arg(args, int);
- b = va_arg(args, int);
- my_func(a, b);
-
- Under Borland-C++, the "..." specifier has also a second usage
- different than the place-holder for varying arguments declaration.
- In an expression, it evaluates directly as a va_list pointer
- to the first varying argument of the function. This makes the
- va-start() macro very simple and more secure, as you can give
- any argument to va_start(), not only the last fixed one.
- However, it can produce confusion when porting to other
- compilers or platforms. So refrain using it like this.
-